package com.hlx.herostory;

import com.hlx.herostory.cmdhandler.CmdHandlerFactory;
import com.hlx.herostory.mq.MQProducer;
import com.hlx.herostory.utils.RedisUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 游戏服务器主入口类
 */
public class ServerMain {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerMain.class);
    private static final int port = 12345;

    /**
     * 应用主函数
     *
     * @param args
     */
    public static void main(String[] args) {
        // 设置log4j属性文件
        PropertyConfigurator.configure(ServerMain.class.getClassLoader().getResourceAsStream("log4j.properties"));
        
        CmdHandlerFactory.init();
        GameMsgRecognizer.init();
        MySqlSessionFactory.init();
        RedisUtil.init();
        MQProducer.init();
        
        // boss处理客户端连接，有连接就建立一个channel，建立后将channel塞给work
        // work负责读写客户端消息，负责业务
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boss, work);
        bootstrap.channel(NioServerSocketChannel.class); // 服务器信道的处理方式
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(
                        new HttpServerCodec(),  // http 服务器编码器
                        new HttpObjectAggregator(65535), // 限制消息长度
                        new WebSocketServerProtocolHandler("/websocket"),
                        new GameMsgDecoder(),  // 自定义消息解码器
                        new GameMsgEncoder(),  // 自定义消息编码器
                        new GameMsgHandler()   // 自定义消息处理器
                );
            }
        });
        try {
            // 注意: 实际项目中会使用 argArray 中的参数来指定端口号
            ChannelFuture future = bootstrap.bind(port).sync();
            if (future.isSuccess()) {
                LOGGER.info("服务器启动成功");
            }
            // 等待服务器信道关闭,
            // 也就是不要退出应用程序,
            // 让应用程序可以一直提供服务
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
